package com.ychs.lawyerback01.service.imp;

import cn.hutool.json.JSONUtil;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ychs.lawyerback01.common.Constant;
import com.ychs.lawyerback01.common.ResultCode;
import com.ychs.lawyerback01.dto.*;
import com.ychs.lawyerback01.exception.BussinessException;
import com.ychs.lawyerback01.mapper.*;
import com.ychs.lawyerback01.pojo.UserEntity;
import com.ychs.lawyerback01.service.UserService;
import com.ychs.lawyerback01.util.JwtUtils;
import com.ychs.lawyerback01.vo.LoginVo;
import com.ychs.lawyerback01.vo.UserDetailVo;
import com.ychs.lawyerback01.vo.UserQueryVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImp implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private JwtUtils jwtUtils;
    @Autowired
    private RedisTemplate redisTemplate;
    //把对象转换成json格式的对象
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private MenuMapper menuMapper;
    @Autowired
    private CertificateMapper certificateMapper;

    @Autowired
    private AcademicMapper academicMapper;

    @Autowired
    private LegalAdvisorMapper legalAdvisorMapper;

    @Autowired
    private WorkChangeMapper workChangeMapper;


    @Value("${file.upload.backup-location}")
    private String baseUploadPath;


    @Override
    public Map<String, Object> login(LoginReqDTO loginReqDTO) throws JsonProcessingException {
        //1.通过用户名查询用户信息
        UserEntity userEntity = userMapper.getUserByUsername(loginReqDTO.getUsername());
        if (userEntity==null){
            throw new BussinessException(ResultCode.LOGIN_USERNAME_ERROR);
        }
        //2.密码是否相等的判断
        Boolean res = passwordEncoder.matches(loginReqDTO.getPassword(),userEntity.getPassword());
        if (!res){
            throw new BussinessException(ResultCode.LOGIN_PWD_ERROR);
        }
        //3.生成token
        Map<String, Object> claims=new HashMap<>();
        claims.put("username",userEntity.getUsername());
        String token = jwtUtils.generateToken(userEntity.getId(), claims);

        //4.获取权限信息
        List<String> permissions = menuMapper.getPermissions(userEntity.getRoleId());
        //5.拷贝信息到vo
        LoginVo loginVo = new LoginVo();
        BeanUtils.copyProperties(userEntity,loginVo);
        //6.把当前用户loginUserVo信息放到redis缓冲中
        loginVo.setToken(token);
        loginVo.setPermission(permissions);
        //objectMapper.writeValueAsString(loginUserVo),
        redisTemplate.opsForValue().set(Constant.TOKEN_PREFIX+userEntity.getId(),
                JSONUtil.toJsonStr(loginVo),
                Constant.TOKEN_TIME, TimeUnit.SECONDS);
        Map<String,Object> map = new HashMap<>();
        map.put("token",token);
        map.put("username",userEntity.getUsername());
        map.put("perms",permissions);
        map.put("id",userEntity.getId());
        return map;
    }

    @Override
    public Map<String, Object> getUsersByCondition(UserQueryDTO queryDTO) {
        // 查询列表
        List<UserQueryVo> userList = userMapper.getUsersByCondition(queryDTO);
        // 查询总数
        int total = userMapper.getCountByCondition(queryDTO);
        // 封装分页结果
        Map<String, Object> result = new HashMap<>();
        result.put("list", userList);
        result.put("total", total);
        result.put("page", queryDTO.getPage());
        result.put("pageSize", queryDTO.getPageSize());
        return result;
    }

    @Override
    public UserDetailVo getUserDetail(Long id) {
        if (id == null) {
            throw new BussinessException(ResultCode.PARAM_ERROR);
        }
        // 查询用户基本信息
        UserEntity user = userMapper.getUserByUserId(id);
        if (user == null) {
            throw new BussinessException(ResultCode.USER_NOT_FOUND);
        }
        // 转换为VO
        UserDetailVo detailVo = new UserDetailVo();
        BeanUtils.copyProperties(user, detailVo);
        // 查询关联数据
        detailVo.setCertificates(certificateMapper.selectByUserId(id));
        detailVo.setAcademics(academicMapper.selectByUserId(id));
        detailVo.setLegalAdvisors(legalAdvisorMapper.selectByUserId(id));
        detailVo.setWorkChanges(workChangeMapper.selectByUserId(id));
        return detailVo;
    }

    @Transactional
    @Override
    public int addUser(UserOptDTO userOptDTO) {
        // 1. 校验身份证号唯一性
        if (userOptDTO.getIdCard() != null) {
            UserEntity existIdCard = userMapper.getUserByIdCard(userOptDTO.getIdCard());
            if (existIdCard != null) {
                throw new BussinessException(ResultCode.ID_CARD_EXIST);
            }
        }
        // 2. 校验执业证号唯一性
        if (userOptDTO.getPracticeCertNo() != null) {
            UserEntity existCert = userMapper.getUserByPracticeCertNo(userOptDTO.getPracticeCertNo());
            if (existCert != null) {
                throw new BussinessException(ResultCode.PRACTICE_CERT_NO_EXIST);
            }
        }

        // 3. 处理文件上传
        UserEntity userEntity = new UserEntity();
        BeanUtils.copyProperties(userOptDTO, userEntity);
        handleFileUploads(userOptDTO, userEntity);

        // 4. 设置默认值
        userEntity.setPassword("123456abc"); // 默认密码
        userEntity.setCreateTime(new Date());
        userEntity.setFlag("0"); // 默认正常状态

        // 5. 保存用户主表
        int rows = userMapper.addUser(userEntity);
        if (rows <= 0) {
            throw new BussinessException(ResultCode.ADD_FAILE);
        }

        // 6. 保存关联表数据
        saveRelatedData(userEntity.getId(), userOptDTO);
        return rows;
    }

    @Transactional
    @Override
    public int editUser(UserOptDTO userOptDTO) {
        if (userOptDTO.getId() == null) {
            throw new BussinessException(ResultCode.PARAM_ERROR);
        }

        // 1. 校验身份证号唯一性（排除自身）
        if (userOptDTO.getIdCard() != null) {
            UserEntity existIdCard = userMapper.getUserByIdCardExceptId(userOptDTO.getIdCard(), userOptDTO.getId());
            if (existIdCard != null) {
                throw new BussinessException(ResultCode.ID_CARD_EXIST);
            }
        }

        // 2. 校验执业证号唯一性（排除自身）
        if (userOptDTO.getPracticeCertNo() != null) {
            UserEntity existCert = userMapper.getUserByPracticeCertNoExceptId(userOptDTO.getPracticeCertNo(), userOptDTO.getId());
            if (existCert != null) {
                throw new BussinessException(ResultCode.PRACTICE_CERT_NO_EXIST);
            }
        }

        // 3. 处理文件上传
        UserEntity userEntity = new UserEntity();
        BeanUtils.copyProperties(userOptDTO, userEntity);
        handleFileUploads(userOptDTO, userEntity);

        // 4. 更新用户主表
        int rows = userMapper.editUser(userEntity);
        if (rows <= 0) {
            throw new BussinessException(ResultCode.UPDATE_FAILE);
        }

        // 5. 先删除旧关联数据，再插入新数据
        deleteRelatedData(userEntity.getId());
        saveRelatedData(userEntity.getId(), userOptDTO);
        return rows;
    }

    @Transactional
    @Override
    public int deleteUser(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            throw new BussinessException(ResultCode.PARAM_ERROR);
        }
        // 1. 删除用户主表
        int rows = userMapper.deleteUser(ids);
        if (rows <= 0) {
            throw new BussinessException(ResultCode.DELETE_FAILE);
        }
        // 2. 批量删除关联表数据
        for (Long id : ids) {
            deleteRelatedData(id);
        }
        return rows;
    }

    // 处理文件上传（照片、简历、证书等）
    private void handleFileUploads(UserOptDTO userOptDTO, UserEntity userEntity) {
        try {
            // 处理头像上传
            if (userOptDTO.getPhotoFile() != null && !userOptDTO.getPhotoFile().isEmpty()) {
                String photoPath = uploadFile(userOptDTO.getPhotoFile(), "photos");
                userEntity.setPhotoPath(photoPath);
            }
            // 处理简历上传
            if (userOptDTO.getResumeFile() != null && !userOptDTO.getResumeFile().isEmpty()) {
                String resumePath = uploadFile(userOptDTO.getResumeFile(), "resumes");
                userEntity.setResumePath(resumePath);
            }
            // 处理证书文件上传
            if (userOptDTO.getCertificates() != null) {
                for (CertificateDTO cert : userOptDTO.getCertificates()) {
                    if (cert.getCertificateFile() != null && !cert.getCertificateFile().isEmpty()) {
                        String certPath = uploadFile(cert.getCertificateFile(), "certificates");
                        cert.setCertificatePath(certPath);
                    }
                }
            }
        } catch (IOException e) {
            throw new BussinessException(ResultCode.FILE_UPLOAD_ERROR, e.getMessage());
        }
    }

    // 通用文件上传方法
    private String uploadFile(MultipartFile file, String subDir) throws IOException {
        // 创建目录（如：/upload/photos/202508/）
        String dateDir = new SimpleDateFormat("yyyyMM").format(new Date());
        File uploadDir = new File(baseUploadPath + "/" + subDir + "/" + dateDir);
        if (!uploadDir.exists()) {
            uploadDir.mkdirs();
        }
        // 生成文件名（原文件名+UUID避免重复）
        String originalFilename = file.getOriginalFilename();
        String ext = originalFilename.substring(originalFilename.lastIndexOf("."));
        String fileName = UUID.randomUUID().toString() + ext;
        // 保存文件
        File destFile = new File(uploadDir, fileName);
        file.transferTo(destFile);

        // 返回绝对路径，使用getAbsolutePath()方法获取文件的绝对路径
        return destFile.getAbsolutePath();
    }

    // 保存关联表数据
    private void saveRelatedData(Long userId, UserOptDTO userOptDTO) {
        // 保存证书
        if (userOptDTO.getCertificates() != null && !userOptDTO.getCertificates().isEmpty()) {
            certificateMapper.batchInsert(userOptDTO.getCertificates(), userId);
        }
        // 保存学术成果
        if (userOptDTO.getAcademics() != null && !userOptDTO.getAcademics().isEmpty()) {
            academicMapper.batchInsert(userOptDTO.getAcademics(), userId);
        }
        // 保存法律顾问单位
        if (userOptDTO.getLegalAdvisors() != null && !userOptDTO.getLegalAdvisors().isEmpty()) {
            legalAdvisorMapper.batchInsert(userOptDTO.getLegalAdvisors(), userId);
        }
        // 保存工作变动记录
        if (userOptDTO.getWorkChanges() != null && !userOptDTO.getWorkChanges().isEmpty()) {
            workChangeMapper.batchInsert(userOptDTO.getWorkChanges(), userId);
        }
    }

    // 删除关联表数据
    private void deleteRelatedData(Long userId) {
        certificateMapper.deleteByUserId(userId);
        academicMapper.deleteByUserId(userId);
        legalAdvisorMapper.deleteByUserId(userId);
        workChangeMapper.deleteByUserId(userId);
    }
}
